#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //设计一个按钮，点击此按钮之后关闭当前窗口
    QPushButton*pushButton=new QPushButton(this);
    pushButton->setText("点击此按钮之后关闭当前窗口");//设置按钮中内容
    pushButton->move(100,200);//设置按钮位置
    //为此按钮配置处理方法
    connect(pushButton,&QPushButton::clicked,this,&Widget::close);
}
//connect函数
//关联信号和槽函数
/*
 *此connect函数和Linux Tcp Socket中建立连接的函数，没有任何关系，只是名称一样
 * connect函数是QObject类提供的静态成员函数
 * Qt中提供的这些类，本身是存在一定的继承关系的
 * Qt中的类的继承关系
 *                                        QObject类
 *                                           |(继承)
 *                 QWidget类                               其他类
 *                    |(继承)                                 |(继承)
 * QPushButton类  QLineEdit类  QTextEdit类...                ....
 *
 * QObject类是其他Qt内置类的祖先节点，即Qt中的所有类都直接或间接继承了QObject类
 * 所以，Qt中的所有类，都可以使用connect函数，因为这个函数是QObject类的静态成员函数
 * 此设定类似java
 * java中所有的类，都是继承自Object类
 *
 * conncet函数具体使用方式
 * connect(const QObject *sender,  //信号源。描述当前信号是由哪个控件发出来的
 *         const char *signal,     //信号类型
 *         //信号如何处理：const QObject *receiver和const char *method参数决定
 *         const QObject *receiver,//此信号由哪个对象负责处理
 *         const char *method,     //这个信号被触发后，这个对象对此信号的处理方法
 *         Qt::ConnectionType type=Qt::AutoConnection //此参数暂不考虑，很少用这个
 * );
 * 所谓的"信号"，也是Qt中的对象内部提供的一些成员函数
 * click:槽函数，作用：在调用这个函数的时候就相当于点击了一下这个按钮
 * clicked:(过去分词)表示点完这个按钮之后，才是要触发的点击信号，就是点完这个按钮之后的信号
 * 图标上带有锯齿形状的是槽函数
 * 图标上的右上角带有波纹形状的是信号函数
 * connect函数要求：信号源和信号类型参数必须要是互相匹配的
 * 例如：信号源控件对象的类型如果是QPushButton，那么信号类型参数必须是QPushButton内置的信号，
 * 这个内置的QPushButton的信号可以由QPushButton对象进行传递，也可以由QPushButton这个类的子类去进行传递，
 * 因为子类可以使用父类的信号。只要能够访问到指定信号源类中的信号即可
 *
 * close()这个槽函数是QWidget内置的槽函数，
 * close()功能在QWidget类内部已经被实现好了，用户只需要调用即可，作用：关闭当前窗口/Widget控件，
 * Widget继承自QWidget，所以Widget对象可以使用父类的槽函数
*/
Widget::~Widget()
{
    delete ui;
}
/*
 * 这里存在一个问题
 * connect(const QObject *sender,
 *         const char *signal,
 *         const QObject *receiver,
 *         const char *method,
 *         Qt::ConnectionType type=Qt::AutoConnection
 * );
 * 这里的信号类型和信号处理函数的参数都是char*,但是实际在使用过程中传入的都是函数指针类型对象
 * 给一个char*的形参里面传递函数指针这显然数据类型对不上，是不合理的
 * 就拿这个例子来说
 * connect(pushButton,&QPushButton::clicked,this,&Widget::close);
 * void clicked(bool checked = false);
 * bool close();
 * 这两个函数指针的类型分别是void(*)(bool)、bool(*)()
 * 但是将这两个函数指针传递给char*的形参中，即使这两个函数指针的类型都不同，居然不报错可以正常运行
 * 在C++中，不允许使用两个不同类型的指针类型，互相赋值，函数传参本质都是赋值(char*本质也是指针类型)
 *
 * 可以正确运行原因：
 * 因为这个第二个和第四个参数的数据类型是char*时期，这个是旧版本的写法(旧版本的connect的声明)
 * 以前确实第二个和第四个参数都必须是const char*的数据类型
 * 以前版本中，传参的写法和现在其实是有区别的
 * 以前要给参数二传递一个信号，这个信号的数据类型是被关联的控件的数据类型中的函数指针，
 * 要将被关联的控件的数据类型中的函数指针转化为const char*数据类型，
 * 需要使用SIGNAL宏
 * 对于参数四也一样，这个信号的处理方式的数据类型就是被关联的控件的数据类型中的函数指针，
 * 同样，要将这个函数指针类型转化为const char*数据类型，
 * 需要使用SLOT宏
 * 之前是这么用的
 * connect(pushButton,SIGANL(&QPushButton::clicked),this,SLOT(&Widget::close));
 * 从Qt5开始之后，对于上述connect()函数的第二、第四个参数的写法做了简化
 * 即不需要写SIGANL、SLOT宏
 * 此版本之后给connect()函数提供了重载版本，重载版本中，将这两个参数调整为泛型函数，允许用户传入任意类型的函数指针
 *
 * 更新之后的好处在于：此时connect()函数有了一个检查功能
 * 即必须保证参数1和参数2的数据类型匹配，即参数1的数据类型为A，参数2的数据类型必须是A类中的函数的函数指针
 * 参数3和参数4的数据类型匹配，即参数3的数据类型为B，参数4的数据类型必须为B类中的函数指针类型
 * 如果对应的参数的数据类型不匹配，那么就会报错
 * 这样的话，编译器会代替程序员去检查这个参数匹配问题
 * 保证了安全性
 *
*/
















